﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls.Primitives;

namespace Edutainment
{
    [Serializable()]
    public class BubbleSort : SortAlgorithm
    {
        public BubbleSort()
            : base("BubbleSort")
        {

        }

        public BubbleSort(int exer, int sExer, int exa, int sExa)
            : base("BubbleSort")
        {
            exercises = exer;
            solvedExercises = sExer;
            exams = exa;
            solvedExams = sExa;
        }

        public bool correctStep(int indxA, int indxB)
        {
            bool correct = false;
            Tuple<int, int> nextStep;
            if (stepList.Count > 0)
            {
                nextStep = (Tuple<int, int>)stepList[0];
                correct = tupleIsEqualToIndices(nextStep, indxA, indxB);
                if (correct)
                {
                    stepList.RemoveAt(0);
                    if (stepList.Count == 0 && sortationDelegate != null)
                    {
                        sortationDelegate.hasCompletedSorting();
                    }
                }
            }
            return correct;
        }

        public void createListToSort(int count, bool exam)
        {
            base.createListToSort(count, exam);
            this.sortForCorrectSteps(listToSort);
        }

        private void sortForCorrectSteps(ArrayList toSort)
        {
            if (toSort != null)
            {
                sortedList = new ArrayList(toSort);
                stepList.Clear();

                int count = toSort.Count;

                for (int i = 0; i < count; i++)
                {
                    int newCount = count - i;
                    for (int k = 0; k < newCount; k++)
                    {
                        int a, b;
                        if (k < newCount - 1)
                        {
                            a = (int)sortedList[k];
                            b = (int)sortedList[k + 1];

                            if (a > b)
                            {
                                this.swap(sortedList, k, k + 1);
                                stepList.Add(new Tuple<int, int>(k, k + 1));
                            }
                        }
                    }
                }
            }
        }

        public bool correctPosition(int index, int number)
        {
            bool correctPosition = false;
            if (index >= 0 && index < sortedList.Count)
            {
                int elementAtIndex = (int)sortedList[index];
                if (elementAtIndex == number)
                    correctPosition = true;
            }
            return correctPosition;
        }

        public void isAtCorrectPosition(ArrayList list, double animDelay)
        {
            if (list != null)
            {
                if (sortationDelegate != null && list.Count > 0)
                {
                    if (list[0] is ToggleButton)
                    {
                        int indx = sortedList.Count - 1;
                        int valAtEnd = (int)((ToggleButton)list[indx]).Content;

                        if (valAtEnd == (int)sortedList[indx])
                        {
                            sortationDelegate.buttonAtCorrectPosition(indx, animDelay);
                            sortedList.RemoveAt(indx);
                        }

                        /*int valAtIndxA = (int)((ToggleButton)list[indxA]).Content;
                        int valAtIndxB = (int)((ToggleButton)list[indxB]).Content;
                        if (stepList.Count >= 1)
                        {
                            if (valAtIndxA > valAtIndxB)
                            {
                                bool correctPosA = this.correctPosition(indxA, valAtIndxA);
                                if (correctPosA)
                                    sortationDelegate.buttonAtCorrectPosition(valAtIndxA);
                            }
                            else
                            {
                                bool correctPosB = this.correctPosition(indxB, valAtIndxB);
                                if (correctPosB)
                                    sortationDelegate.buttonAtCorrectPosition(valAtIndxB);
                            }
                        }
                        else
                        {
                            bool correctPosA = this.correctPosition(indxA, valAtIndxA);
                            if (correctPosA)
                                sortationDelegate.buttonAtCorrectPosition(valAtIndxA);
                            bool correctPosB = this.correctPosition(indxB, valAtIndxB);
                            if (correctPosB)
                                sortationDelegate.buttonAtCorrectPosition(valAtIndxB);
                        }*/
                    }
                }
            }
        }

        public void swap(ArrayList list, int indxA, int indxB)
        {
            if (list != null && indxA >= 0 && indxA < list.Count && indxB >= 0 && indxB < list.Count)
            {
                Object temp = (Object)list[indxB];
                list[indxB] = list[indxA];
                list[indxA] = temp;

                isAtCorrectPosition(list, 0);

                if (stepList.Count == 0 && sortationDelegate != null)
                {
                    double animDelay = 0.5;
                    while (sortedList.Count > 0)
                    {
                        isAtCorrectPosition(sortationDelegate.buttonList, animDelay);
                        animDelay += 0.5;
                    }
                }
            }
        }

        private bool tupleIsEqualToIndices(Tuple<int, int> tuple, int indxA, int indxB)
        {
            if (tuple != null)
            {
                if (tuple.Item1 == indxA && tuple.Item2 == indxB || tuple.Item1 == indxB && tuple.Item2 == indxA)
                    return true;
            }

            return false;
        }

        public Tuple<int, int> getNextStep()
        {
            if (stepList != null && stepList.Count > 0)
            {
                return (Tuple<int, int>)stepList[0];
            }
            return null;
        }
    }
}
